#IOT
#pip3 install -i https://pypi.doubanio.com/simple paho-mqtt
import paho.mqtt.client as mqtt
import time, os, subprocess, sys
import win32con  # win32gui, win32api,
import ctypes
from IOTMqtt import IOTControl
import base
from update import Update

    
class Function:
    def __init__(self,信息发送途径):
        #super(Function, self).__init__()#同步上级变量
        print(sys.argv[0] )
        self.所有功能名 = ['WinCmd', '返回信息', 'GetInfo', '退出', '更新程序', 'ComCmd', 'MsgBox', 'StartCmd', 'ReStart']  # 库的所有指令
        self.所有功能 = [self.WinCmd, self.返回信息, self.GetInfo, self.退出, self.更新程序, self.ComCmd, self.MsgBox, self.StartCmd, self.ReStart]  # 所有功能
        self.信息服务 = 信息发送途径

    def main_loop(self,命令队列,服务连接状态):
        time.sleep(0.1)
        while 命令队列.empty() == False and 服务连接状态:
            命令组 = 命令队列.get()
            print("INFO CMD 05: 获取的命令>>> ", 命令组)
            print("INFO CMD 06: 运行的函数名或代码", 命令组[0])
            if 命令组[0] in self.所有功能名:
                print("INFO CMD 07: 函数命令 寻找函数")
                N = self.所有功能名.index(命令组[0])
                print("INFO CMD 08: 函数编号: {0} 函数名: {1} 函数参数: {2}".format(N, 命令组[0], 命令组[1]))
                self.所有功能[N](命令组[1])
            elif base.基础().是不是整数(命令组[0]) and int(命令组[0]) <= len(self.所有功能):
                print("INFO CMD 09: 函数代码 寻找函数")
                print("INFO CMD 10: 函数编号: {0} 函数名: {1} 函数参数: {2}".format(
                    int(命令组[0]), 命令组[0], 命令组[1]))
                self.所有功能[int(命令组[0])](命令组[1])  # 执行相应的函数

    def WinCmd(self,cmd):
        print("INFO CMD 11: ","执行的命令", cmd)
        try:
            p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            # 响应码及内容
            stdout, stderr = p.communicate(timeout=600)
            print("    执行结果", stdout.decode("gbk"))
            print("    执行结果", stderr.decode("gbk"))
            print("    执行状态", p.returncode)
        except:
            self.返回信息("{0}>>{1}".format(cmd, "There are some problem"))
            print("INFO CMD 13:", cmd, " Run Error")
        else:
            if len(str(stdout.decode("gbk"))) >= 15:
                rMsg = ("".join((str(stdout.decode("gbk"))).split()))
                rMsg = (rMsg)[-10:-1]
            elif len(str(stdout.decode("gbk"))) < 15 and len(str(stdout.decode("gbk"))) != 0:
                rMsg = (str(stdout.decode("gbk")))
            else:
                rMsg = ''
            if p.returncode == 0:#如果命令执行成功
                self.返回信息("{0}>>{1}".format(cmd, "Your CMD Has Run"))
                print("INFO CMD 12:", cmd, " Run Success")
                time.sleep(0.1)
                if rMsg != '':
                    self.返回信息(rMsg)#向MQTT反馈
            else:#命令执行失败
                self.返回信息("{0}>>{1}".format(cmd, "There are some problem"))
                print("INFO CMD 13:", cmd, " Run Error")

    def GetInfo(self,cmd):
        print("INFO CMD 14: ", "执行的命令", cmd)
        try:
            p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            # 响应码及内容
            stdout, stderr = p.communicate(timeout=10)
            print("    执行结果",stdout.decode("gbk"))
            print("    执行结果",stderr.decode("gbk"))
            print("    执行状态",p.returncode)
        except:
            # p.kill()
            self.返回信息("{0}>>{1}".format(cmd, "There are some problem"))
            print("INFO CMD 15:", cmd, " Run Error")
        else:
            rMsg = ("".join((str(stdout.decode("gbk"))).split()))
            self.返回信息("{0}>>{1}".format(cmd, "Your CMD Has Run"))
            print("INFO CMD 16:", cmd, " Run Success")
            if rMsg != '':
                self.返回信息(rMsg)#向MQTT反馈
            else:#命令执行失败
                self.返回信息("{0}>>{1}".format(cmd, "There are some problem"))
                print("INFO CMD 17:", cmd, " Run Error")
            
    def ComCmd(self,cmd):
        try:
            print(cmd)
            subprocess.Popen(cmd)
            self.返回信息("{0}>>{1}".format(cmd, "Def Has Run"))
        except:
            self.返回信息("{0}>>{1}".format(cmd, "There are some problem"))
            print("INFO CMD 13:", cmd, " Run Error")

    def StartCmd(self,path):
        try:
            print(path)
            os.system("start {0}".format(path))
            self.返回信息("{0}>>{1}".format(path, "Path Has Run"))
        except:
            self.返回信息("{0}>>{1}".format(path, "There are some problem"))
            print("INFO CMD 13:", path, " Run Error")
    def 返回信息(self,信息):
        self.信息服务.发布信息(信息)

    def MsgBox(self, message, 标题='Tip', 显示时长=10):
        print("INFO CMD 21: ","显示弹窗，内容为: ",message)
        # 判断变量是否合法
        ret = ctypes.windll.user32.MessageBoxTimeoutW(
            0, message, str(标题), win32con.MB_OK, 0, int(int(显示时长)*1000))
        print("INFO CMD 22: ","用户处理: ", ret)
        self.返回信息('MsgBoxRun')  # 反馈
        print("INFO CMD 23: ", "弹窗已关闭")
       
    def 退出 (self,W='word'):
        self.服务.退出()
        sys.exit(0)#结束运行

    def ReStart(self,软件路径):
        #软件名称 = base.基础().加载配置文档['软件']['主程序名称']
        #软件路径 = base.基础().加载配置文档['软件']['路径']
        #软件位置 = os.path.join(软件名称, 软件路径)
        os.system('start %s'%sys.argv[0])
        sys.exit(0)
        
    def 检查网络(self):#检查网络
        print("INFO START 14: ","检查网络连接")
        import subprocess
        cmd = 'ping iot.dfrobot.com -n 2'
        #PIDS=subprocess.getstatusoutput(cmd)
        网络状态 =subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        网络状态.wait()
        网络状态 = 网络状态.returncode
        #网络状态 =  str(网络状态.stdout.read(), encoding='gbk')
        #print(网络状态.returncode)
        #while self.proc.poll() == None:
        #    pass
        print(网络状态)
        if 网络状态 == 0:
            print("INFO START 15: ", "网络连接正常")
        else:
            print("INFO START 15: ", "网络异常或不佳")
        if 网络状态 == 0:
            self.信息服务.re_connect()
        return 网络状态
    
    def 更新程序(self,V=''):
        time.sleep(5)
        print("INFO START 16","正在检查更新")
        云端版本号 = Update().云端版本()
        本地版本号 = base.基础().加载配置文档()['软件']['版本号']
        print("本地版本号", 本地版本号)
        if 云端版本号 > 本地版本号:
            print("发现新版本,版本号为:", 云端版本号)
            已下载的文件 = Update.下载文件()
            更新命令文件位置 = os.path.join(
                os.path.split(sys.argv[0])[0], 'UpDate.bat')
            with open(更新命令文件位置, 'w') as 命令文件:
                temp = "echo 正在更新至最新版本...\n"
                for 文件名 in 已下载的文件:
                    文件名称 = os.path.splitext(文件名)[0]
                    temp += "timeout /t 2 /nobreak\n"
                    temp += "taskkill /f /im {0}.exe\n".format(文件名称)
                    temp += "del {0}.exe\n".format(文件名称)  # 删除旧程序
                    temp += "ren {0}.newexe {0}.exe".format(文件名称)  # 复制新版本程序
                    temp += "echo {0}更新完成\n".format(文件名称)
                    temp += "timeout /t 3 /nobreak\n"
                temp += "start {0}".format(
                    base.基础().加载配置文档()['软件']['主程序名称'])   
                temp += "exit"
                print(temp)
                命令文件.write(temp)
            if 已下载的文件 != []:
                os.system("start {}".format(更新命令文件位置))
        else:
            print('当前版本已是最新')


        

if __name__ == '__main__':
    测试 = IOTControl(base.基础().加载配置文档())
    测试.re_connect()
    命令队列 = 测试.命令队列
    Com = Function(测试)
    print("调试")
    #Com.Update('test')
    while True:
        Com.main_loop(命令队列, 1)
